/*
 * Copyright Notice ====================================================
 * This file contains proprietary information of Hewlett-Packard Co.
 * Copying or reproduction without prior written approval is prohibited.
 * Copyright (c) 2013 All rights reserved. =============================
 */

package com.hp.ecs.sonar.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.FastDateFormat;

/**
 * @since fanhoujun 2008-3-20
 */
public class DateUtil {

	private static long debugTime = 0;

	public static void debugCurrentDate(Date debugDate) {
		if (debugDate == null) {
			return;
		}
		final long time = debugDate.getTime();
		debugTime = time - time % MILLIS_PER_DAY + MILLIS_PER_DAY;
	}

	/** 1000 */
	public static final long MILLIS_PER_SECOND = 1000;

	/** 60×1000 */
	public static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;

	/** 60×60×1000 */
	public static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;

	/** 24×60×60×1000 */
	public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR;

	/** yyyyMMdd */
	public static final String COMPACT_DATE_PATTERN = "yyyyMMdd";

	/** yyyy-MM-dd */
	public static final String DATE_PATTERN = "yyyy-MM-dd";

	/** yyyy-MM-dd HH:mm:ss */
	public static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

	/** yyyy-MM-dd HH:mm */
	public static final String TRIM_SECOND_PATTERN = "yyyy-MM-dd HH:mm";

	/** yyyyMMdd HH:mm */
	public static final String COMPACT_TRIM_SECOND_PATTERN = "yyyyMMdd HH:mm";

	/** default pattern: yyyy-MM-dd */
	public static Date parse(String str) {
		return parse(str, DATE_PATTERN);
	}

	public static Date parse(String str, String pattern) {
		if (StringUtils.isBlank(str)) {
			return null;
		}
		DateFormat parser = new SimpleDateFormat(pattern);
		try {
			return parser.parse(str);
		} catch (ParseException e) {
			throw new IllegalArgumentException("Can't parse " + str + " using " + pattern);
		}
	}

	public static Date currentDate() {
		if (debugTime == 0) {
			return new Date();
		} else {
			return new Date(debugTime + System.currentTimeMillis() % MILLIS_PER_DAY);
		}
	}

	public static int curDay() {
		return Integer.parseInt(DateUtil.format("yyyyMMdd"));
	}

	public static String format(String pattern) {
		return format(currentDate(), pattern);
	}

	public static String format(Date date) {
		return format(date, DATE_PATTERN);
	}

	public static String format(Date date, String pattern) {
		if (date == null) {
			return null;
		}
		return FastDateFormat.getInstance(pattern).format(date);
	}

	public static Date trim(Date date, int type) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		boolean tmp = type == Calendar.MONTH;
		if (tmp) {
			cal.set(Calendar.MONTH, 0);
		}
		tmp |= type == Calendar.DAY_OF_MONTH;
		if (tmp) {
			cal.set(Calendar.DAY_OF_MONTH, 1);
		}
		tmp |= type == Calendar.HOUR_OF_DAY;
		if (tmp) {
			cal.set(Calendar.HOUR_OF_DAY, 0);
		}
		tmp |= type == Calendar.MINUTE;
		if (tmp) {
			cal.set(Calendar.MINUTE, 0);
		}
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}

	public static Date addHours(Date date, int hours) {
		return add(date, Calendar.HOUR_OF_DAY, hours);
	}

	public static Date addMinutes(Date date, int minutes) {
		return add(date, Calendar.MINUTE, minutes);
	}

	public static Date addDays(Date date, int days) {
		return add(date, Calendar.DATE, days);
	}

	public static Date addMonths(Date date, int months) {
		return add(date, Calendar.MONTH, months);
	}

	public static Date addYears(Date date, int years) {
		return add(date, Calendar.YEAR, years);
	}

	private static Date add(Date date, int field, int amount) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(field, amount);
		return cal.getTime();
	}
}
